1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.collect;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkNotNull;
21 import static com.google.common.base.Predicates.and;
22 import static com.google.common.base.Predicates.in;
23 import static com.google.common.base.Predicates.not;
24 import static com.google.common.collect.CollectPreconditions.checkNonnegative;
25 import static com.google.common.math.LongMath.binomial;
26
27 import com.google.common.annotations.Beta;
28 import com.google.common.annotations.GwtCompatible;
29 import com.google.common.base.Function;
30 import com.google.common.base.Joiner;
31 import com.google.common.base.Predicate;
32 import com.google.common.base.Predicates;
33 import com.google.common.math.IntMath;
34 import com.google.common.primitives.Ints;
35
36 import java.util.AbstractCollection;
37 import java.util.ArrayList;
38 import java.util.Arrays;
39 import java.util.Collection;
40 import java.util.Collections;
41 import java.util.Comparator;
42 import java.util.Iterator;
43 import java.util.List;
44
45 import javax.annotation.Nullable;
46
47
48
49
50
51
52
53
54
55 @GwtCompatible
56 public final class Collections2 {
57 private Collections2() {}
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89 public static <E> Collection<E> filter(
90 Collection<E> unfiltered, Predicate<? super E> predicate) {
91 if (unfiltered instanceof FilteredCollection) {
92
93
94 return ((FilteredCollection<E>) unfiltered).createCombined(predicate);
95 }
96
97 return new FilteredCollection<E>(
98 checkNotNull(unfiltered), checkNotNull(predicate));
99 }
100
101
102
103
104
105
106 static boolean safeContains(
107 Collection<?> collection, @Nullable Object object) {
108 checkNotNull(collection);
109 try {
110 return collection.contains(object);
111 } catch (ClassCastException e) {
112 return false;
113 } catch (NullPointerException e) {
114 return false;
115 }
116 }
117
118
119
120
121
122
123 static boolean safeRemove(Collection<?> collection, @Nullable Object object) {
124 checkNotNull(collection);
125 try {
126 return collection.remove(object);
127 } catch (ClassCastException e) {
128 return false;
129 } catch (NullPointerException e) {
130 return false;
131 }
132 }
133
134 static class FilteredCollection<E> extends AbstractCollection<E> {
135 final Collection<E> unfiltered;
136 final Predicate<? super E> predicate;
137
138 FilteredCollection(Collection<E> unfiltered,
139 Predicate<? super E> predicate) {
140 this.unfiltered = unfiltered;
141 this.predicate = predicate;
142 }
143
144 FilteredCollection<E> createCombined(Predicate<? super E> newPredicate) {
145 return new FilteredCollection<E>(unfiltered,
146 Predicates.<E>and(predicate, newPredicate));
147
148 }
149
150 @Override
151 public boolean add(E element) {
152 checkArgument(predicate.apply(element));
153 return unfiltered.add(element);
154 }
155
156 @Override
157 public boolean addAll(Collection<? extends E> collection) {
158 for (E element : collection) {
159 checkArgument(predicate.apply(element));
160 }
161 return unfiltered.addAll(collection);
162 }
163
164 @Override
165 public void clear() {
166 Iterables.removeIf(unfiltered, predicate);
167 }
168
169 @Override
170 public boolean contains(@Nullable Object element) {
171 if (safeContains(unfiltered, element)) {
172 @SuppressWarnings("unchecked")
173 E e = (E) element;
174 return predicate.apply(e);
175 }
176 return false;
177 }
178
179 @Override
180 public boolean containsAll(Collection<?> collection) {
181 return containsAllImpl(this, collection);
182 }
183
184 @Override
185 public boolean isEmpty() {
186 return !Iterables.any(unfiltered, predicate);
187 }
188
189 @Override
190 public Iterator<E> iterator() {
191 return Iterators.filter(unfiltered.iterator(), predicate);
192 }
193
194 @Override
195 public boolean remove(Object element) {
196 return contains(element) && unfiltered.remove(element);
197 }
198
199 @Override
200 public boolean removeAll(final Collection<?> collection) {
201 return Iterables.removeIf(unfiltered, and(predicate, in(collection)));
202 }
203
204 @Override
205 public boolean retainAll(final Collection<?> collection) {
206 return Iterables.removeIf(unfiltered, and(predicate, not(in(collection))));
207 }
208
209 @Override
210 public int size() {
211 return Iterators.size(iterator());
212 }
213
214 @Override
215 public Object[] toArray() {
216
217 return Lists.newArrayList(iterator()).toArray();
218 }
219
220 @Override
221 public <T> T[] toArray(T[] array) {
222 return Lists.newArrayList(iterator()).toArray(array);
223 }
224 }
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245 public static <F, T> Collection<T> transform(Collection<F> fromCollection,
246 Function<? super F, T> function) {
247 return new TransformedCollection<F, T>(fromCollection, function);
248 }
249
250 static class TransformedCollection<F, T> extends AbstractCollection<T> {
251 final Collection<F> fromCollection;
252 final Function<? super F, ? extends T> function;
253
254 TransformedCollection(Collection<F> fromCollection,
255 Function<? super F, ? extends T> function) {
256 this.fromCollection = checkNotNull(fromCollection);
257 this.function = checkNotNull(function);
258 }
259
260 @Override public void clear() {
261 fromCollection.clear();
262 }
263
264 @Override public boolean isEmpty() {
265 return fromCollection.isEmpty();
266 }
267
268 @Override public Iterator<T> iterator() {
269 return Iterators.transform(fromCollection.iterator(), function);
270 }
271
272 @Override public int size() {
273 return fromCollection.size();
274 }
275 }
276
277
278
279
280
281
282
283
284
285
286
287
288
289 static boolean containsAllImpl(Collection<?> self, Collection<?> c) {
290 return Iterables.all(c, Predicates.in(self));
291 }
292
293
294
295
296 static String toStringImpl(final Collection<?> collection) {
297 StringBuilder sb
298 = newStringBuilderForCollection(collection.size()).append('[');
299 STANDARD_JOINER.appendTo(
300 sb, Iterables.transform(collection, new Function<Object, Object>() {
301 @Override public Object apply(Object input) {
302 return input == collection ? "(this Collection)" : input;
303 }
304 }));
305 return sb.append(']').toString();
306 }
307
308
309
310
311 static StringBuilder newStringBuilderForCollection(int size) {
312 checkNonnegative(size, "size");
313 return new StringBuilder((int) Math.min(size * 8L, Ints.MAX_POWER_OF_TWO));
314 }
315
316
317
318
319 static <T> Collection<T> cast(Iterable<T> iterable) {
320 return (Collection<T>) iterable;
321 }
322
323 static final Joiner STANDARD_JOINER = Joiner.on(", ").useForNull("null");
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352 @Beta public static <E extends Comparable<? super E>>
353 Collection<List<E>> orderedPermutations(Iterable<E> elements) {
354 return orderedPermutations(elements, Ordering.natural());
355 }
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404 @Beta public static <E> Collection<List<E>> orderedPermutations(
405 Iterable<E> elements, Comparator<? super E> comparator) {
406 return new OrderedPermutationCollection<E>(elements, comparator);
407 }
408
409 private static final class OrderedPermutationCollection<E>
410 extends AbstractCollection<List<E>> {
411 final ImmutableList<E> inputList;
412 final Comparator<? super E> comparator;
413 final int size;
414
415 OrderedPermutationCollection(Iterable<E> input,
416 Comparator<? super E> comparator) {
417 this.inputList = Ordering.from(comparator).immutableSortedCopy(input);
418 this.comparator = comparator;
419 this.size = calculateSize(inputList, comparator);
420 }
421
422
423
424
425
426
427
428
429
430
431 private static <E> int calculateSize(
432 List<E> sortedInputList, Comparator<? super E> comparator) {
433 long permutations = 1;
434 int n = 1;
435 int r = 1;
436 while (n < sortedInputList.size()) {
437 int comparison = comparator.compare(
438 sortedInputList.get(n - 1), sortedInputList.get(n));
439 if (comparison < 0) {
440
441 permutations *= binomial(n, r);
442 r = 0;
443 if (!isPositiveInt(permutations)) {
444 return Integer.MAX_VALUE;
445 }
446 }
447 n++;
448 r++;
449 }
450 permutations *= binomial(n, r);
451 if (!isPositiveInt(permutations)) {
452 return Integer.MAX_VALUE;
453 }
454 return (int) permutations;
455 }
456
457 @Override public int size() {
458 return size;
459 }
460
461 @Override public boolean isEmpty() {
462 return false;
463 }
464
465 @Override public Iterator<List<E>> iterator() {
466 return new OrderedPermutationIterator<E>(inputList, comparator);
467 }
468
469 @Override public boolean contains(@Nullable Object obj) {
470 if (obj instanceof List) {
471 List<?> list = (List<?>) obj;
472 return isPermutation(inputList, list);
473 }
474 return false;
475 }
476
477 @Override public String toString() {
478 return "orderedPermutationCollection(" + inputList + ")";
479 }
480 }
481
482 private static final class OrderedPermutationIterator<E>
483 extends AbstractIterator<List<E>> {
484
485 List<E> nextPermutation;
486 final Comparator<? super E> comparator;
487
488 OrderedPermutationIterator(List<E> list,
489 Comparator<? super E> comparator) {
490 this.nextPermutation = Lists.newArrayList(list);
491 this.comparator = comparator;
492 }
493
494 @Override protected List<E> computeNext() {
495 if (nextPermutation == null) {
496 return endOfData();
497 }
498 ImmutableList<E> next = ImmutableList.copyOf(nextPermutation);
499 calculateNextPermutation();
500 return next;
501 }
502
503 void calculateNextPermutation() {
504 int j = findNextJ();
505 if (j == -1) {
506 nextPermutation = null;
507 return;
508 }
509
510 int l = findNextL(j);
511 Collections.swap(nextPermutation, j, l);
512 int n = nextPermutation.size();
513 Collections.reverse(nextPermutation.subList(j + 1, n));
514 }
515
516 int findNextJ() {
517 for (int k = nextPermutation.size() - 2; k >= 0; k--) {
518 if (comparator.compare(nextPermutation.get(k),
519 nextPermutation.get(k + 1)) < 0) {
520 return k;
521 }
522 }
523 return -1;
524 }
525
526 int findNextL(int j) {
527 E ak = nextPermutation.get(j);
528 for (int l = nextPermutation.size() - 1; l > j; l--) {
529 if (comparator.compare(ak, nextPermutation.get(l)) < 0) {
530 return l;
531 }
532 }
533 throw new AssertionError("this statement should be unreachable");
534 }
535 }
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557 @Beta public static <E> Collection<List<E>> permutations(
558 Collection<E> elements) {
559 return new PermutationCollection<E>(ImmutableList.copyOf(elements));
560 }
561
562 private static final class PermutationCollection<E>
563 extends AbstractCollection<List<E>> {
564 final ImmutableList<E> inputList;
565
566 PermutationCollection(ImmutableList<E> input) {
567 this.inputList = input;
568 }
569
570 @Override public int size() {
571 return IntMath.factorial(inputList.size());
572 }
573
574 @Override public boolean isEmpty() {
575 return false;
576 }
577
578 @Override public Iterator<List<E>> iterator() {
579 return new PermutationIterator<E>(inputList);
580 }
581
582 @Override public boolean contains(@Nullable Object obj) {
583 if (obj instanceof List) {
584 List<?> list = (List<?>) obj;
585 return isPermutation(inputList, list);
586 }
587 return false;
588 }
589
590 @Override public String toString() {
591 return "permutations(" + inputList + ")";
592 }
593 }
594
595 private static class PermutationIterator<E>
596 extends AbstractIterator<List<E>> {
597 final List<E> list;
598 final int[] c;
599 final int[] o;
600 int j;
601
602 PermutationIterator(List<E> list) {
603 this.list = new ArrayList<E>(list);
604 int n = list.size();
605 c = new int[n];
606 o = new int[n];
607 Arrays.fill(c, 0);
608 Arrays.fill(o, 1);
609 j = Integer.MAX_VALUE;
610 }
611
612 @Override protected List<E> computeNext() {
613 if (j <= 0) {
614 return endOfData();
615 }
616 ImmutableList<E> next = ImmutableList.copyOf(list);
617 calculateNextPermutation();
618 return next;
619 }
620
621 void calculateNextPermutation() {
622 j = list.size() - 1;
623 int s = 0;
624
625
626
627 if (j == -1) {
628 return;
629 }
630
631 while (true) {
632 int q = c[j] + o[j];
633 if (q < 0) {
634 switchDirection();
635 continue;
636 }
637 if (q == j + 1) {
638 if (j == 0) {
639 break;
640 }
641 s++;
642 switchDirection();
643 continue;
644 }
645
646 Collections.swap(list, j - c[j] + s, j - q + s);
647 c[j] = q;
648 break;
649 }
650 }
651
652 void switchDirection() {
653 o[j] = -o[j];
654 j--;
655 }
656 }
657
658
659
660
661 private static boolean isPermutation(List<?> first,
662 List<?> second) {
663 if (first.size() != second.size()) {
664 return false;
665 }
666 Multiset<?> firstMultiset = HashMultiset.create(first);
667 Multiset<?> secondMultiset = HashMultiset.create(second);
668 return firstMultiset.equals(secondMultiset);
669 }
670
671 private static boolean isPositiveInt(long n) {
672 return n >= 0 && n <= Integer.MAX_VALUE;
673 }
674 }